//
//  sharePtr.hpp
//  learnC++
//
//  Created by liuzhibing on 2018/7/1.
//  Copyright © 2018年 yunfan.com. All rights reserved.
//

#ifndef sharePtr_hpp
#define sharePtr_hpp

#include <stdio.h>
#include <iostream>

//与std :: unique_ptr不同，它被设计为单独拥有和管理一个资源，std :: shared_ptr是为了解决你需要多个智能指针共同拥有资源的情况。
//这意味着可以有多个std :: shared_ptr指向相同的资源。 在内部，std :: shared_ptr跟踪有多少std :: shared_ptr共享资源。 只要至少有一个std :: shared_ptr指向资源，即使单个std :: shared_ptr被销毁，资源也不会被释放。 一旦管理资源的最后一个std :: shared_ptr超出范围（或被重新分配指向其他内容），该资源将被释放。


/*
 //正确
Resource *res = new Resource();
std::shared_ptr<Resource> ptr1(res);
{
    //std::shared_ptr<Resource> *ptr2 = new std::shared_ptr<Resource>(ptr1);
//   delete ptr2;
    std::shared_ptr<Resource> ptr2(ptr1);//NOTE
}
 
//错误
 Resource *res = new Resource;
 std::shared_ptr<Resource> ptr1(res);
 {
 std::shared_ptr<Resource> ptr2(res); //NOTE
 
 std::cout << "Killing one shared pointer\n";
 } // ptr2 goes out of scope here, and the allocated Resource is destroyed
 
 std::cout << "Killing another shared pointer\n";
 
 //std::make_shared
 auto ptr1 = std::make_shared<Resource>();
 {
 auto ptr2 = ptr1;
 }
 
*/

//规则：如果您需要指向同一资源的多个std :: shared_ptr，则始终复制现有的std :: shared_ptr。

/*
 共享指针可以从唯一指针创建
 
 std :: unique_ptr可以通过一个特殊的std :: shared_ptr构造函数转换为std :: shared_ptr，该构造函数接受std :: unique_ptr的r值。 std :: unique_ptr的内容将被移至std :: shared_ptr，如：
 
 auto unique = std::make_unique<Resource>();
 std::shared_ptr<Resource> share(std::move(unique));
 
 但是，std :: shared_ptr无法安全地转换为std :: unique_ptr。这意味着如果你正在创建一个将返回一个智能指针的函数，那么最好返回一个std :: unique_ptr，并在合适的时候将它分配给std :: shared_ptr。
 
 std :: shared_ptr的危险
 
 std :: shared_ptr与std :: unique_ptr有一些相同的挑战 - 如果std :: shared_ptr没有正确处理（或者是因为它是动态分配的并且从不删除的，或者它是动态分配的对象的一部分并且从不删除），那么它所管理的资源也不会被解除分配。使用std :: unique_ptr，你只需要担心一个智能指针被正确处置。用std :: shared_ptr，你必须担心其他管理的share_ptr。如果管理资源的任何std :: shared_ptr未正确销毁，则不会正确释放资源。
 
 std :: shared_ptr和数组
 
 在C ++ 14及更早版本中，std :: shared_ptr没有对数组进行适当的支持，因此不应该用于管理C风格的数组。从C ++ 17开始，std :: share_ptr确实支持数组。但是，从C ++ 17开始，std :: make_shared仍然缺乏对数组的适当支持，不应该用于创建共享数组。这可能会在C ++ 20中解决。
 
 结论
 
 std :: shared_ptr是为需要共同管理同一资源的多个智能指针而设计的。当管理资源的最后一个std :: shared_ptr被销毁时，资源将被释放。
 
 最好使用std::make_shared
 如果Something的构造函数抛出异常，则其中一个Somethings可能无法正确释放。
 解决方案是使用make_shared：
 class Something; // assume Something is a class that can throw an exception
 
 int main()
 {
 doSomething(std::make_shared<Something>(), std::make_shared<Something>());
 
 return 0;
 }
 
 */

#endif /* sharePtr_hpp */
